OpenClaw 记忆管理完全指南
记忆是 AI 助理保持连续性和个性化的关键。OpenClaw 提供 memory_search 和 memory_get 两个工具,支持语义搜索和精确读取记忆文件。本文详细介绍如何高效使用这些工具构建有"记忆"的 AI 助理。
一、工具概述
memory_search - 语义搜索
在记忆文件中搜索相关内容:
- 支持语义理解(不仅仅是关键词匹配)
- 搜索范围:MEMORY.md + memory/*.md
- 返回最相关的片段及位置
- 可设置最小相关度和最大结果数
javascript
// 基本搜索
memory_search(query="用户偏好")
// 设置参数
memory_search(
query="项目截止日期",
minScore=0.7, // 最小相关度(0-1)
maxResults=5 // 最多返回结果数
)memory_get - 精确读取
从指定记忆文件读取特定行:
- 精确控制读取位置
- 支持从某行开始读取指定行数
- 适合读取已知位置的内容
javascript
// 读取整个文件
memory_get(path="MEMORY.md")
// 从第 10 行开始读取 20 行
memory_get(path="memory/2026-03-19.md", from=10, lines=20)二、记忆文件结构
工作区文件
~/.openclaw/workspace/
├── MEMORY.md # 长期记忆(主会话专用)
├── SOUL.md # AI 人格定义
├── USER.md # 用户信息
├── TOOLS.md # 工具配置和本地笔记
└── memory/
├── 2026-03-17.md # 每日记忆
├── 2026-03-18.md
└── 2026-03-19.mdMEMORY.md - 长期记忆
用途: 存储需要长期记住的重要信息
特点:
- 只在主会话(与用户直接对话)加载
- 群聊、共享会话不加载(安全考虑)
- 需要人工或 AI 定期整理更新
内容示例:
# 长期记忆
## 用户偏好
- 称呼:老大
- 回复风格:简洁,不啰嗦
- 执行风格:严格命令,不耍滑头
## 重要日期
- 用户生日:1990-05-15
- 项目上线:2026-03-17
## 项目信息
- 网站名称:AiTimes 智能时代
- 域名:www.AiTimes.net
- 技术栈:OpenClaw + VitePressmemory/YYYY-MM-DD.md - 每日记忆
用途: 记录当天的重要事件和对话
特点:
- 每天一个文件
- 自动创建(如不存在)
- 详细记录原始对话和事件
内容示例:
# 2026-03-19
## 重要对话
- 06:05 用户指出文章质量问题
- 06:30 重新发布 7 篇详实文章
- 07:00 总结经验并写入 TOOLS.md
## 完成的任务
- ✅ 发布 7 篇教程文章
- ✅ 建立文章发布流程
- ✅ 配置防重复机制
## 学到的经验
- 质量优先于速度
- 建立标准化流程
- 及时记录经验三、实战案例 1:个性化对话
场景说明
记住用户的偏好、历史对话,提供个性化的回复和服务。
完整实现
javascript
// 个性化对话管理器
class PersonalizedChat {
constructor() {
this.userPrefs = null
this.loadUserPrefs()
}
// 加载用户偏好
async loadUserPrefs() {
try {
// 搜索用户偏好相关记忆
const result = memory_search(
query="用户偏好 称呼 风格 习惯",
maxResults=5
)
// 解析偏好
this.userPrefs = this.parsePrefs(result)
} catch (e) {
console.log("未找到用户偏好,使用默认设置")
this.userPrefs = {
address: "用户",
style: "friendly"
}
}
}
// 解析偏好
parsePrefs(searchResult) {
const prefs = {}
// 提取称呼
const addressMatch = searchResult.match(/称呼 [::]\s*(.+)/)
prefs.address = addressMatch ? addressMatch[1].trim() : "用户"
// 提取回复风格
const styleMatch = searchResult.match(/回复风格 [::]\s*(.+)/)
prefs.style = styleMatch ? styleMatch[1].trim() : "friendly"
// 提取执行风格
const execMatch = searchResult.match(/执行风格 [::]\s*(.+)/)
prefs.exec = execMatch ? execMatch[1].trim() : "normal"
return prefs
}
// 生成个性化回复
generateResponse(message, context) {
// 根据偏好调整回复风格
if (this.userPrefs.style.includes("简洁")) {
return this.conciseResponse(message, context)
} else if (this.userPrefs.style.includes("详细")) {
return this.detailedResponse(message, context)
} else {
return this.normalResponse(message, context)
}
}
// 记录对话到记忆
async recordConversation(userMessage, aiResponse) {
const today = new Date().toISOString().split('T')[0]
const memoryPath = `memory/${today}.md`
// 读取今日记忆
let todayMemory = ""
try {
todayMemory = memory_get(path=memoryPath)
} catch (e) {
// 文件不存在,创建新文件
}
// 追加对话记录
const entry = `
## 对话记录 - ${new Date().toLocaleTimeString('zh-CN')}
**用户**: ${userMessage.substring(0, 100)}...
**AI**: ${aiResponse.substring(0, 100)}...
`
write(path=memoryPath, content=todayMemory + entry)
}
}
// 使用示例
const chat = new PersonalizedChat()
// 生成回复
const response = chat.generateResponse(
"帮我写个报告",
{ topic: "项目进度", deadline: "明天" }
)
// 记录对话
await chat.recordConversation("帮我写个报告", response)个性化回复示例
// 用户偏好:简洁
用户:"帮我写个报告"
AI:"好的,报告主题和截止日期是?"
// 用户偏好:详细
用户:"帮我写个报告"
AI:"好的,我很乐意帮您写报告。请告诉我:
1. 报告的主题是什么?
2. 报告的用途(汇报/总结/计划)?
3. 需要包含哪些部分?
4. 截止日期是什么时候?
5. 有没有字数要求?"四、实战案例 2:项目进度跟踪
场景说明
记住项目的关键节点、待办事项、决策记录,随时回答项目相关问题。
完整实现
javascript
// 项目记忆管理器
class ProjectMemory {
constructor(projectName) {
this.projectName = projectName
this.memoryTag = `项目:${projectName}`
}
// 记录项目决策
async recordDecision(decision, rationale, alternatives) {
const entry = `
## 项目决策 - ${new Date().toISOString()}
**决策**: ${decision}
**理由**: ${rationale}
**备选方案**: ${alternatives}
**标签**: ${this.memoryTag}
`
// 追加到 MEMORY.md
let memory = ""
try {
memory = memory_get(path="MEMORY.md")
} catch (e) {
memory = `# ${this.projectName} 项目记忆\n`
}
write(path="MEMORY.md", content=memory + entry)
}
// 记录待办事项
async recordTodo(todo, priority, deadline) {
const entry = `
## 待办 - ${new Date().toISOString()}
**任务**: ${todo}
**优先级**: ${priority}
**截止**: ${deadline}
**状态**: 待办
**标签**: ${this.memoryTag}
`
let memory = ""
try {
memory = memory_get(path="MEMORY.md")
} catch (e) {
memory = `# ${this.projectName} 项目记忆\n`
}
write(path="MEMORY.md", content=memory + entry)
}
// 更新待办状态
async updateTodoStatus(todoId, status, notes) {
// 搜索相关待办
const result = memory_search(
query=`${this.memoryTag} 待办 ${todoId}`,
maxResults=1
)
// 更新状态(需要手动编辑文件)
// 这里简化处理,实际应使用 edit 工具
console.log(`更新待办 ${todoId} 状态为 ${status}`)
}
// 查询项目信息
async queryProjectInfo(query) {
// 搜索项目相关记忆
const result = memory_search(
query=`${this.memoryTag} ${query}`,
maxResults=10
)
return this.formatQueryResult(result)
}
// 格式化查询结果
formatQueryResult(searchResult) {
// 提取决策、待办、笔记等
const decisions = searchResult.match(/## 项目决策.*?(?=##|$)/gs) || []
const todos = searchResult.match(/## 待办.*?(?=##|$)/gs) || []
return {
decisions: decisions.map(d => this.parseDecision(d)),
todos: todos.map(t => this.parseTodo(t)),
total: decisions.length + todos.length
}
}
}
// 使用示例
const project = new ProjectMemory("AiTimes 网站")
// 记录技术选型决策
await project.recordDecision(
"使用 VitePress 作为静态网站生成器",
"轻量、快速、支持 Markdown,适合文档类网站",
"备选:VuePress, Docusaurus, GitBook"
)
// 添加待办事项
await project.recordTodo(
"完成首页设计",
"高",
"2026-03-20"
)
// 查询项目信息
const info = await project.queryProjectInfo("技术选型")
console.log(`找到 ${info.total} 条相关信息`)查询结果示例
查询:"技术选型"
找到 3 条相关信息
## 项目决策 - 2026-03-17
**决策**: 使用 VitePress 作为静态网站生成器
**理由**: 轻量、快速、支持 Markdown,适合文档类网站
**备选方案**: VuePress, Docusaurus, GitBook
## 项目决策 - 2026-03-18
**决策**: 使用 Gitee Pages 部署
**理由**: 国内访问速度快,免费额度够用
**备选方案**: GitHub Pages, Vercel, Netlify五、实战案例 3:学习笔记管理
场景说明
记录学习过程中的重点、疑问、心得,形成可搜索的知识库。
完整实现
javascript
// 学习笔记管理器
class LearningNotes {
constructor(subject) {
this.subject = subject
this.notesFile = `memory/learning-${subject}.md`
}
// 添加学习笔记
async addNote(topic, content, tags) {
const entry = `
## ${topic} - ${new Date().toISOString()}
${content}
**标签**: ${tags.join(', ')}
**主题**: ${this.subject}
---
`
let notes = ""
try {
notes = memory_get(path=this.notesFile)
} catch (e) {
notes = `# ${this.subject} 学习笔记\n\n`
}
write(path=this.notesFile, content=notes + entry)
}
// 记录疑问
async recordQuestion(question, context) {
const entry = `
## ❓ 疑问 - ${new Date().toISOString()}
**问题**: ${question}
**上下文**: ${context}
**状态**: 待解答
---
`
let notes = ""
try {
notes = memory_get(path=this.notesFile)
} catch (e) {
notes = `# ${this.subject} 学习笔记\n\n`
}
write(path=this.notesFile, content=notes + entry)
}
// 解答疑问
async answerQuestion(questionId, answer) {
// 搜索疑问
const result = memory_search(
query=`${this.subject} 疑问 ${questionId}`,
maxResults=1
)
// 更新笔记(简化处理)
console.log(`解答疑问 ${questionId}: ${answer}`)
}
// 复习笔记
async reviewNotes(topics, interval='7d') {
// 搜索相关笔记
const results = []
for (const topic of topics) {
const result = memory_search(
query=`${this.subject} ${topic}`,
maxResults=5
)
results.push({ topic, result })
}
// 生成复习计划
const reviewPlan = `
# 复习计划 - ${this.subject}
生成时间:${new Date().toLocaleString('zh-CN')}
复习周期:${interval}
## 复习内容
${results.map(r => `
### ${r.topic}
找到 ${r.result.split('##').length - 1} 条相关笔记
`).join('\n')}
## 复习建议
1. 先看概览,再看细节
2. 重点关注标记为"重点"的内容
3. 解答之前的疑问
4. 记录新的理解
`
return reviewPlan
}
// 导出笔记
async exportNotes(format='markdown') {
const notes = memory_get(path=this.notesFile)
if (format === 'markdown') {
return notes
} else if (format === 'json') {
// 解析为 JSON 格式
const sections = notes.split('## ').slice(1)
return sections.map(s => {
const [title, ...content] = s.split('\n')
return {
title: title.split(' - ')[0],
date: title.split(' - ')[1],
content: content.join('\n')
}
})
}
}
}
// 使用示例
const learning = new LearningNotes("OpenClaw")
// 添加学习笔记
await learning.addNote(
"记忆管理工具",
`
memory_search 用于语义搜索记忆文件。
memory_get 用于精确读取指定位置。
使用场景:
1. 记住用户偏好
2. 跟踪项目进度
3. 管理学习笔记
注意事项:
- MEMORY.md 只在主会话加载
- 定期整理,删除过时信息
`,
["工具", "记忆", "重点"]
)
// 记录疑问
await learning.recordQuestion(
"如何保证记忆的安全性?",
"记忆文件包含敏感信息,如何防止泄露?"
)
// 复习笔记
const plan = await learning.reviewNotes(["工具", "安全", "最佳实践"])
console.log(plan)学习笔记示例
# OpenClaw 学习笔记
## 记忆管理工具 - 2026-03-19T08:00:00.000Z
memory_search 用于语义搜索记忆文件。
memory_get 用于精确读取指定位置。
使用场景:
1. 记住用户偏好
2. 跟踪项目进度
3. 管理学习笔记
注意事项:
- MEMORY.md 只在主会话加载
- 定期整理,删除过时信息
**标签**: 工具,记忆,重点
**主题**: OpenClaw
---
## ❓ 疑问 - 2026-03-19T08:05:00.000Z
**问题**: 如何保证记忆的安全性?
**上下文**: 记忆文件包含敏感信息,如何防止泄露?
**状态**: 待解答
---六、高级技巧
1. 定期整理记忆
javascript
// 每周整理记忆,删除过时信息
async function weeklyMemoryCleanup() {
// 读取 MEMORY.md
let memory = memory_get(path="MEMORY.md")
// 提取所有日期
const dates = memory.match(/\d{4}-\d{2}-\d{2}/g) || []
// 找出 3 个月前的内容
const threeMonthsAgo = new Date()
threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3)
const outdatedDates = dates.filter(d => new Date(d) < threeMonthsAgo)
if (outdatedDates.length > 0) {
console.log(`发现 ${outdatedDates.length} 条过时内容`)
// 可以归档或删除
// 注意:删除前询问用户
}
}2. 记忆备份
javascript
// 定期备份记忆文件
async function backupMemories() {
const timestamp = Date.now()
const backupDir = `~/.openclaw/backups/memory-${timestamp}`
// 创建备份目录
exec(command=`mkdir -p ${backupDir}`)
// 备份 MEMORY.md
try {
const memory = memory_get(path="MEMORY.md")
write(path=`${backupDir}/MEMORY.md`, content=memory)
} catch (e) {
console.log("MEMORY.md 不存在,跳过")
}
// 备份每日记忆
const dailyFiles = exec(
command="ls ~/.openclaw/workspace/memory/*.md",
capture_output=True
).stdout.trim().split('\n')
for (const file of dailyFiles) {
if (file) {
const filename = file.split('/').pop()
const content = read(path=file)
write(path=`${backupDir}/${filename}`, content=content)
}
}
console.log(`✅ 记忆备份完成:${backupDir}`)
}3. 记忆导入导出
javascript
// 导出记忆为 JSON
async function exportMemories() {
const memory = memory_get(path="MEMORY.md")
// 解析为结构化数据
const sections = memory.split(/^## /m).slice(1)
const structured = sections.map(section => {
const [title, ...lines] = section.split('\n')
return {
title: title.trim(),
content: lines.join('\n').trim()
}
})
return {
exportedAt: new Date().toISOString(),
totalSections: structured.length,
data: structured
}
}
// 从 JSON 导入记忆
async function importMemories(jsonData) {
let memory = "# 长期记忆\n\n"
for (const section of jsonData.data) {
memory += `## ${section.title}\n\n${section.content}\n\n`
}
write(path="MEMORY.md", content=memory)
console.log(`✅ 导入 ${jsonData.data.length} 条记忆`)
}七、最佳实践
1. 记忆分类
✅ 好的分类:
- 用户偏好
- 项目信息
- 学习笔记
- 重要日期
- 决策记录
❌ 差的分类:
- 把所有内容都堆在一起
- 没有标签和日期
- 不区分长期和短期记忆2. 定期更新
javascript
// ✅ 好的做法:每天回顾,每周整理
// 每天:记录当天重要事件到 memory/YYYY-MM-DD.md
// 每周:整理 MEMORY.md,删除过时信息
// 每月:导出备份,防止数据丢失
// ❌ 差的做法:
// - 从不整理,记忆文件越来越大
// - 只记录不删除,包含大量过时信息
// - 不备份,数据丢失风险3. 安全考虑
javascript
// ✅ 好的做法:
// - 敏感信息加密存储
// - MEMORY.md 只在主会话加载
// - 群聊中不读取个人记忆
// - 定期审查记忆内容
// ❌ 差的做法:
// - 在群聊中暴露用户隐私
// - 记忆文件包含明文密码
// - 不审查就记录所有对话八、常见问题
Q: memory_search 和 web_search 有什么区别?
A:
memory_search: 搜索本地记忆文件(语义搜索)web_search: 搜索互联网(基于 Brave API)
Q: 如何确保记忆的准确性?
A:
- 记录时注明来源和时间
- 定期回顾和验证
- 用户确认重要信息
- 标记不确定的内容
Q: 记忆文件太大怎么办?
A:
- 定期整理,删除过时信息
- 归档旧记忆到单独文件
- 使用搜索而非全量读取
- 分主题存储(如 learning-xxx.md)
Q: 可以在群聊中使用记忆吗?
A:
- 可以,但要注意安全
- MEMORY.md 只在主会话自动加载
- 群聊中手动读取时避免暴露隐私
- 敏感信息使用加密存储
九、总结
记忆管理让 AI 助理更有"人性":
| 工具 | 用途 | 特点 |
|---|---|---|
| memory_search | 语义搜索 | 理解意图,返回相关片段 |
| memory_get | 精确读取 | 控制位置,适合已知内容 |
掌握记忆管理,你可以:
- 记住用户偏好,提供个性化服务
- 跟踪项目进度,随时回答疑问
- 管理学习笔记,形成知识库
- 保持对话连续性,提升体验
记住:好的记忆 = 准确记录 + 定期整理 + 安全存储
相关资源: